import inspect
from functools import wraps


def log_function_info(func):
    """通用装饰器：记录函数/方法的元信息和调用参数"""
    func_name = func.__name__
    module_name = func.__module__
    package_name = '.'.join(module_name.split('.')[:-1]) if '.' in module_name else ''
    sig = inspect.signature(func)

    @wraps(func)
    def wrapper(*args, **kwargs):
        # 绑定实际参数
        bound = sig.bind(*args, **kwargs)
        bound.apply_defaults()

        # 判断是否是类中的方法（通过 __qualname__）
        is_method = '.' in func.__qualname__ and '<locals>' not in func.__qualname__
        class_name = func.__qualname__.rsplit('.', 1)[0] if is_method else None

        print("=== 函数/方法调用日志 ===")
        print(f"类型:       {'类方法' if isinstance(func, classmethod) else ('实例方法' if is_method else '普通函数')}")
        print(f"函数名:     {func_name}")
        if class_name:
            print(f"所属类:     {class_name}")
        print(f"模块:       {module_name}")
        print(f"包名:       {package_name or '(顶层模块)'}")
        print(f"签名:       {sig}")
        print(f"实参:       {dict(bound.arguments)}")
        print("========================\n")

        return func(*args, **kwargs)

    return wrapper


class Calculator:
    """一个简单的计算器类"""

    def __init__(self, name="DefaultCalc"):
        self.name = name

    @log_function_info
    def add(self, a: int, b: int) -> int:
        """普通实例方法：需要 self"""
        return a + b

    @classmethod
    @log_function_info
    def create_default(cls):
        """类方法：使用 @classmethod，第一个参数是 cls"""
        return cls(name="DefaultFromClassMethod")

    @staticmethod
    @log_function_info
    def multiply(a: int, b: int) -> int:
        """静态方法：无 self 或 cls"""
        return a * b
